/**
 * 
 */
package sk.lukaskrupa.guess.the.color.core;

import static sk.lukaskrupa.guess.the.color.core.ApplicationConstants.MAX_GUESSES;
import static sk.lukaskrupa.guess.the.color.core.ApplicationConstants.MAX_ROWS;

import java.io.Serializable;

import sk.lukaskrupa.guess.the.color.logging.Logging;
import sk.lukaskrupa.guess.the.color.utils.GuessColorUtil;
import android.util.SparseArray;

/**
 * Contains methods and fields related to back end board representation.
 * 
 * @author Lukas Krupa (lukas0krupa@gmail.com)
 * 
 */
public class Board implements Serializable {

	private static final long serialVersionUID = -3436630189834992948L;

	private static Logging logger = Logging.getLog(Board.class);

	private int guessingRow = 1;

	private final SparseArray<SparseArray<ColorEnum>> guesses = new SparseArray<SparseArray<ColorEnum>>(10);
	private final SparseArray<SparseArray<ColorEnum>> results = new SparseArray<SparseArray<ColorEnum>>(10);
	private SparseArray<ColorEnum> hiddenRow;

	/**
	 * Initial back end board with HIDDEN (1st row NONE) color and generate
	 * colors for guessing).
	 * 
	 * @param hiddenRow
	 *            generated somewhere else and will be used
	 */
	public void initBoard(SparseArray<ColorEnum> hiddenRow) {

		this.guessingRow = 1;

		// Generating hidden colors
		logger.info("initBoard", "Starting generation of hidden colors.");
		this.hiddenRow = hiddenRow;
		logger.info("initBoard", "Generation done. " + GuessColorUtil.printSparseArray(this.hiddenRow));

		// Setting back end board
		ColorEnum toSet = ColorEnum.NONE;
		for (int rowIndex = 1; rowIndex <= MAX_ROWS; rowIndex++) {

			this.guesses.put(rowIndex, new SparseArray<ColorEnum>(MAX_GUESSES));
			this.results.put(rowIndex, new SparseArray<ColorEnum>(MAX_GUESSES));

			for (int columnIndex = 1; columnIndex <= MAX_GUESSES; columnIndex++) {
				this.guesses.get(rowIndex).append(columnIndex, toSet);
				this.results.get(rowIndex).append(columnIndex, toSet);
			}

			if (rowIndex == 1) {
				toSet = ColorEnum.HIDDEN;
			}
		}
	}
	/**
	 * Set current row Color
	 * 
	 * @param columnIndex
	 *            at which color changes
	 * @param newColor
	 *            what was chosen
	 */
	public void setButtonColortTo(int columnIndex, int newColor) {
		logger.debug("setButtonColorTo", "Row=" + this.guessingRow + ", Column=" + columnIndex);
		logger.debug("setButtonColorTo", "Guess row: " + GuessColorUtil.printSparseArray(this.guesses.get(this.guessingRow)));
		logger.debug("setButtonColorTo", "Value before " + this.guesses.get(this.guessingRow).get(columnIndex));

		this.guesses.get(this.guessingRow).put(columnIndex, ColorEnum.getColorById(newColor));
	}

	/**
	 * Continue with next row and set it to NONE color (ligth Grey).
	 */
	public void increaseGuessingRow() {
		this.guessingRow += 1;
		for (int columIndex = 1; columIndex <= MAX_GUESSES; columIndex++) {
			this.guesses.get(this.guessingRow).put(columIndex, ColorEnum.NONE);
			this.results.get(this.guessingRow).put(columIndex, ColorEnum.NONE);
		}
	}

	/**
	 * checks if all guesses are filled.
	 * 
	 * @return true only if all guesses are there.
	 */
	public boolean hasAllGuesses() {

		for (int columnIndex = 1; columnIndex <= MAX_GUESSES; columnIndex++) {

			if (this.guesses.get(this.guessingRow).get(columnIndex).equals(ColorEnum.NONE)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Gets button status at certain position.
	 * 
	 * @param row
	 *            to be given
	 * @param column
	 *            to be given
	 * @return Drawable ID
	 */
	public int getButtonStatusAt(int row, int column, boolean guesses) {

		logger.trace("getButtonStatusAt", "Row=" + row + ", Column=" + column + ", CheckingGuesses=" + guesses);
		if (guesses) {
			return this.guesses.get(row).get(column).getDrawableId();
		} else {
			return this.results.get(row).get(column).getDrawableId();

		}
	}

	/**
	 * Returns logger for Classes that need to use them.
	 * 
	 * (Some code was moved from here, and want keep correct logger)
	 * 
	 * @return
	 */
	public static Logging getLogger(Class<?> requestor) {

		if (requestor.equals(GameVariantSpecificActions.class)) {
			return logger;
		}

		// NullPointer exception will occur, if somebody else will call this
		return null;
	}
	/**
	 * Gets hiddenRow.
	 * 
	 * @return the hiddenRow
	 */
	public SparseArray<ColorEnum> getHiddenRow() {
		return this.hiddenRow;
	}
	/**
	 * Sets hiddenRow.
	 * 
	 * @param hiddenRow
	 *            the hiddenRow to set
	 */
	public void setHiddenRow(SparseArray<ColorEnum> hiddenRow) {
		this.hiddenRow = hiddenRow;
	}
	/**
	 * Gets guessingRow.
	 * 
	 * @return the guessingRow
	 */
	public int getGuessingRow() {
		return this.guessingRow;
	}
	/**
	 * Gets guesses.
	 * 
	 * @return the guesses
	 */
	public SparseArray<SparseArray<ColorEnum>> getGuesses() {
		return this.guesses;
	}
	/**
	 * Gets results.
	 * 
	 * @return the results
	 */
	public SparseArray<SparseArray<ColorEnum>> getResults() {
		return this.results;
	}

}
